﻿package com.hutra.utils
{

    final public class Number3D extends Object
    {
        private var vy:Number;
        private var num:Number3D;
        private var mod:Number;
        private var vx:Number;
        private var _scale:Number;
        private var vz:Number;
        private const MathPI:Number = 3.14159;
        private var dist:Number;
        public var x:Number;
        public var y:Number;
        public var z:Number;
        public static var BACKWARD:Number3D = new Number3D(0, 0, -1);
        public static var FORWARD:Number3D = new Number3D(0, 0, 1);
        public static var LEFT:Number3D = new Number3D(-1, 0, 0);
        public static var DOWN:Number3D = new Number3D(0, -1, 0);
        public static var UP:Number3D = new Number3D(0, 1, 0);
        public static var RIGHT:Number3D = new Number3D(1, 0, 0);

        public function Number3D(param1:Number = 0, param2:Number = 0, param3:Number = 0, param4:Number = 1, param5:Boolean = false)
        {
            this.x = param1;
            this.y = param2;
            this.z = param3;
            this._scale = param4;
            if (param5)
            {
                normalize();
            }
            return;
        }// end function

        public function sub(param1:Number3D, param2:Number3D) : void
        {
            x = param1.x - param2.x;
            y = param1.y - param2.y;
            z = param1.z - param2.z;
            return;
        }// end function

        public function distanceinXYPlane(param1:Number3D) : Number
        {
            var _loc_2:* = Math.sqrt(Math.pow(param1.y - y, 2) + Math.pow(param1.x - x, 2));
            return _loc_2;
        }// end function

        public function cross(param1:Number3D, param2:Number3D) : void
        {
            if (param1 == this || param2 == this)
            {
                throw new Error("resultant cross product cannot be the same instance as an input");
            }
            x = param2.y * param1.z - param2.z * param1.y;
            y = param2.z * param1.x - param2.x * param1.z;
            z = param2.x * param1.y - param2.y * param1.x;
            return;
        }// end function

        public function get scale() : Number
        {
            return _scale;
        }// end function

        public function dot(param1:Number3D) : Number
        {
            return x * param1.x + y * param1.y + z * param1.z;
        }// end function

        public function getXYAngle(param1:Number3D) : Number
        {
            var _loc_2:Number = 0;
            _loc_2 = Math.acos(Math.abs(param1.x - x) / distance(param1)) * 180 / Math.PI;
            return _loc_2;
        }// end function

        public function closestPointOnPlane(param1:Number3D, param2:Number3D, param3:Number3D) : Number3D
        {
            if (!num)
            {
                num = new Number3D();
            }
            num.sub(param1, param2);
            dist = param3.dot(num);
            num.scaleNumberBy(param3, dist);
            num.sub(param1, num);
            return num;
        }// end function

        public function interpolate(param1:Number3D, param2:Number) : void
        {
            var _loc_3:* = new Number3D();
            _loc_3.sub(param1, this);
            _loc_3.scaleNumberBy(_loc_3, param2);
            add(this, _loc_3);
            return;
        }// end function

        public function set scale(param1:Number) : void
        {
            _scale = param1;
            return;
        }// end function

        public function clone(param1:Number3D) : void
        {
            x = param1.x;
            y = param1.y;
            z = param1.z;
            return;
        }// end function

        public function getAngle(param1:Number3D = null) : Number
        {
            if (param1 == null)
            {
                param1 = new Number3D();
            }
            return Math.acos(dot(param1) / (modulo * param1.modulo));
        }// end function

        public function normalize(param1:Number = 1) : void
        {
            mod = modulo / param1;
            if (mod != 0 && mod != 1)
            {
                x = x / mod;
                y = y / mod;
                z = z / mod;
            }
            return;
        }// end function

        public function add(param1:Number3D, param2:Number3D) : void
        {
            x = param1.x + param2.x;
            y = param1.y + param2.y;
            z = param1.z + param2.z;
            return;
        }// end function

        public function scaleNumberBy(param1:Number3D, param2:Number) : void
        {
            x = param1.x * param2;
            y = param1.y * param2;
            z = param1.z * param2;
            return;
        }// end function

        public function toString() : String
        {
            return "x:" + x + " y:" + y + " z:" + z;
        }// end function

        public function distance(param1:Number3D) : Number
        {
            return Math.sqrt((x - param1.x) * (x - param1.x) + (y - param1.y) * (y - param1.y) + (z - param1.z) * (z - param1.z));
        }// end function

        public function get modulo() : Number
        {
            return Math.sqrt(x * x + y * y + z * z);
        }// end function

        public function get modulo2() : Number
        {
            return x * x + y * y + z * z;
        }// end function

        public function equals(param1:Number3D) : Boolean
        {
            return param1.x == x && param1.y == y && param1.z == z;
        }// end function

        public static function getInterpolated(param1:Number3D, param2:Number3D, param3:Number) : Number3D
        {
            var _loc_4:* = new Number3D();
            _loc_4.sub(param1, param2);
            _loc_4.scaleNumberBy(_loc_4, param3);
            _loc_4.add(_loc_4, param2);
            return _loc_4;
        }// end function

    }
}
